package goodsController

import (
	"CMETO/models"
	"CMETO/utils"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

type GoodsTypeController struct{}

// @Summary 商品分类查询（树状所有）
// @Description 树状查询商品分类
// @Tags 商品分类管理
// @Accept json
// @Produce json
// @param name query string false "商品分类名"
// @Success 200 {object} models.ResultCommon[[]models.GoodsType] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /goodsType [get]
// @Security JWT
func (r GoodsTypeController) QueryGoodsTypes(ctx *gin.Context) {
	nameStr := ctx.DefaultQuery("name", "")
	name := "%" + nameStr + "%"
	var goodsType []models.GoodsType
	if err := models.DB.Preload("Children", "is_delete=0 AND name like ?", name).Preload("Children.Children", "is_delete=0 AND name like ?", name).Where("fid=0 AND is_delete=0 AND name like ?", name).Find(&goodsType).Error; err != nil {
		ctx.JSON(http.StatusOK, models.ResultCommon[string]{
			Msg:    "查询失败",
			Code:   "400",
			Result: "",
		})
	} else {
		ctx.JSON(http.StatusOK, models.ResultCommon[[]models.GoodsType]{
			Msg:    "查询成功",
			Code:   "200",
			Result: goodsType,
		})
	}
}

// @Summary 商品分类新增
// @Description 新增商品分类
// @Tags 商品分类管理
// @Accept json
// @Produce json
// @Param deptInfo body models.GoodsType true "商品分类信息"
// @Success 200 {object} models.AddResult "新增成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.AddResult "新增失败"
// @Router /goodsType [post]
// @Security JWT
func (d GoodsTypeController) AddGoodsType(ctx *gin.Context) {
	goodsType := &models.GoodsType{}
	// 绑定json数据
	if err := ctx.ShouldBindJSON(&goodsType); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "数据错误",
			Code:   "400",
			Result: nil,
		})
	} else {
		goodsType.CreateTime = utils.TimeFormatter(time.Now())
		var result = models.DB.Model(&models.GoodsType{}).Create(&goodsType).RowsAffected
		// 返回
		if result != 1 {
			ctx.JSON(http.StatusOK, &models.AddResult{
				Msg:    "新增失败",
				Code:   "400",
				Result: result,
			})
		} else {
			ctx.JSON(http.StatusOK, &models.AddResult{
				Msg:    "新增成功",
				Code:   "200",
				Result: result,
			})
		}
	}
}

// @Summary 商品分类修改
// @Description 修改商品分类
// @Tags 商品分类管理
// @Accept json
// @Produce json
// @Param deptInfo body models.GoodsType true "商品分类信息"
// @Success 200 {object} models.UpdateResult[models.GoodsType] "更新成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.AddResult "修改失败"
// @Router /goodsType [put]
// @Security JWT
func (d GoodsTypeController) UpdateGoodsType(ctx *gin.Context) {
	var goodsType models.GoodsType
	// 绑定json数据
	if err := ctx.ShouldBindJSON(&goodsType); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "数据绑定失败",
			Code:   "400",
			Result: err,
		})
		return
	}
	goodsType_old := &models.GoodsType{}

	models.DB.First(&goodsType_old, goodsType.Id)
	if goodsType_old.Id == 0 {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "更新失败",
			Code:   "400",
			Result: nil,
		})
		return
	}
	result := models.DB.Model(&goodsType_old).Save(&goodsType)
	if result.RowsAffected == 0 {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "更新失败",
			Code:   "400",
			Result: nil,
		})
	} else {
		ctx.JSON(http.StatusOK, &models.UpdateResult[models.GoodsType]{
			Msg:    "更新成功",
			Code:   "200",
			Result: goodsType,
		})
	}
}

// @Summary 删除商品分类
// @Description 传入json，批量删除商品分类
// @Tags 商品分类管理
// @Accept json
// @Produce json
// @Param deptsIds body models.DeleteParams true "商品分类id合集"
// @Success 200 {object} models.DeleteResult "更新成功"
// @fail 400 {object} models.ErrorResult "数据错误"
// @fail 401 {object} models.DeleteResult "删除失败"
// @Router /goodsType [delete]
// @Security JWT
func (d GoodsTypeController) DeleteGoodsType(ctx *gin.Context) {
	// 绑定参数实例
	ids := &models.DeleteParams{}
	// 定义模型实例
	var goodsType models.GoodsType
	if err := ctx.ShouldBindJSON(&ids); err != nil {
		ctx.JSON(http.StatusOK, &models.ErrorResult{
			Msg:    "删除失败",
			Code:   "400",
			Result: err,
		})
	} else {
		// 假的删
		result := models.DB.Model(&goodsType).Where("id IN (?)", ids.Ids).Update("is_delete", 1)
		if result.RowsAffected != 0 {
			ctx.JSON(http.StatusOK, &models.DeleteResult{
				Msg:    "删除成功",
				Code:   "200",
				Result: ids.Ids,
			})
		} else {
			ctx.JSON(http.StatusOK, &models.DeleteResult{
				Msg:    "删除失败",
				Code:   "400",
				Result: []int{0},
			})
		}
	}
}

// @Summary 分类查询
// @Description 查询所有顶级分类
// @Tags 分类管理
// @Accept json
// @Produce json
// @Success 200 {object} models.ResultCommon[models.GoodsType] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /goodsType/upper/ [get]
// @Security JWT
func (d GoodsTypeController) QueryTypeUpper(ctx *gin.Context) {
	var goodsType []models.GoodsType
	err := models.DB.Model(&models.GoodsType{}).Where("fid = 0 AND is_delete = 0").Find(&goodsType).Error
	if err == nil {
		ctx.JSON(http.StatusOK, models.ResultCommon[[]models.GoodsType]{
			Msg:    "ok",
			Code:   "200",
			Result: goodsType,
		})
	} else {
		ctx.JSON(http.StatusOK, models.ResultCommon[string]{
			Msg:    "no",
			Code:   "200",
			Result: "",
		})
	}
}

// @Summary 分类查询
// @Description 查询所有上级分类
// @Tags 分类管理
// @Accept json
// @Produce json
// @Param id path string false "当前分类id"
// @Success 200 {object} models.ResultCommon[models.GoodsType] "查询成功"
// @Success 401 {object} models.ResultCommon[string] "查询失败"
// @Router /goods/upper/:id [get]
// @Security JWT
func (d GoodsTypeController) QueryAllUpper(ctx *gin.Context) {
	id, _ := strconv.Atoi(ctx.Param("id"))
	if result, _ := GetAncestorDept(id); result != nil {
		ctx.JSON(http.StatusOK, models.ResultCommon[[]models.GoodsType]{
			Msg:    "ok",
			Code:   "200",
			Result: result,
		})
	} else {
		ctx.JSON(http.StatusOK, models.ResultCommon[string]{
			Msg:    "no",
			Code:   "200",
			Result: "",
		})
	}
}

func GetAncestorDept(id int) ([]models.GoodsType, error) {
	var goodsType []models.GoodsType
	err := models.DB.Model(&models.GoodsType{}).Where("id = ? AND is_delete = 0", id).Find(&goodsType).Error
	if err != nil {
		return nil, err
	}
	if len(goodsType) == 0 {
		return nil, err
	}
	ancestorMenus, err := GetAncestorDept(goodsType[0].FId)
	if err != nil {
		return nil, err
	}
	return append(ancestorMenus, goodsType...), nil
}
